using FrameOperateSync;
using UnityEngine;

namespace Pvp.Ecs
{
    using System.Collections.Generic;
    using System;
    public static class Entities
    {
        private static Dictionary<Type, int> _ComponentTypeMap;
        private static List<List<IDataComponent>> _ComponentList;
        private static Dictionary<int, ISingleDataComponent> _SingleComponentMap;

        public static IEnumerable<T> GetComponents<T>() where T : IDataComponent
        {
            if(_ComponentTypeMap.TryGetValue(typeof(T),out var x))
            {
                return Covert<T>(_ComponentList[x]);
            }

            throw new Exception($"GetComponents error, type is {typeof(T)}");
        }

        public static void AddComponent<T>(T value) where T : IDataComponent
        {
            AddComponent(typeof(T),value);
        }
        
        public static void AddComponent(Type type, IDataComponent value)
        {
            if (_ComponentTypeMap.TryGetValue(type, out var x))
            {
                _ComponentList[x].Add(value);
            }
        }

        public static void AddSingleComponent<T>() where T : ISingleDataComponent,new()
        {
            AddSingleComponent(typeof(T),new T());
        }
        
        public static void AddSingleComponent(Type type, ISingleDataComponent value)
        {
            if (_ComponentTypeMap.TryGetValue(type, out var x))
            {
                _SingleComponentMap.Add(x,value);
            }
        }

        public static T GetSingleComponent<T>() where T : ISingleDataComponent
        {
            if(_ComponentTypeMap.TryGetValue(typeof(T),out var x))
            {
                return (T)_SingleComponentMap[x];
            }
            
            throw new Exception($"GetSingleComponent error, type is {typeof(T)}");
        }

        static IEnumerable<T> Covert<T>(List<IDataComponent> list) where T : IDataComponent
        {
            List<T> tlist = new List<T>(list.Count);
            foreach (var tmp in list)
            {
                tlist.Add((T)tmp);
            }

            return tlist;
        }

        [RuntimeInitializeOnLoadMethod]
        public static void Init()
        {
            Debug.LogError(111);
            
            _ComponentTypeMap = new Dictionary<Type, int>();
            _ComponentList = new List<List<IDataComponent>>();
            _SingleComponentMap = new Dictionary<int, ISingleDataComponent>();
            
            _ComponentTypeMap.Add(typeof(IUnit),1);
            _ComponentTypeMap.Add(typeof(IMove),2);
            _ComponentTypeMap.Add(typeof(ILifeUnit),3);
            _ComponentTypeMap.Add(typeof(IGearUnit),4);
            _ComponentTypeMap.Add(typeof(IAnimator),5);
            _ComponentTypeMap.Add(typeof(IView),6);
            _ComponentTypeMap.Add(typeof(IController),7);
            _ComponentTypeMap.Add(typeof(IStage),8);
            _ComponentTypeMap.Add(typeof(IPlayerInput),9);


            for (int i = 0; i < 9; i++)
            {
                _ComponentList.Add(new List<IDataComponent>());
            }
        }
    }

    public static class Systemes
    {
        private static List<ISystem> systemList;

        public static void Start()
        {
            foreach (var sys in systemList)
            {
                sys.OnStart();
            }
        }

        public static void Update(int frameIndex)
        {
            foreach (var sys in systemList)
            {
                sys.OnFrameExecute(frameIndex);
            }
        }

        static Systemes()
        {
            systemList = new List<ISystem>();
            
            systemList.Add(new UnitGearSystem());
            systemList.Add(new StageSystem());
            systemList.Add(new UnitMoveSystem());
            systemList.Add(new UnitInputSystem());
            systemList.Add(new UnitViewSystem());
            systemList.Add(new UnitControllerSystem());
        }
    }

    public static class ViewUtility
    {
        private static GameObject _viewRoot = null;
        public static void CreateView(IView view)
        {
            GameObject obj = new GameObject($"view_{view.BelongEntityId}");
            obj.AddComponent<CustomView>().SetView(view);
            
            obj.transform.SetParent(_viewRoot.transform);
        }

        static ViewUtility()
        {
            _viewRoot = new GameObject("__ViewRoot");
            _viewRoot.AddComponent<ViewRootInstance>();
        }

        class ViewRootInstance : MonoBehaviour
        {
            private void Awake()
            {
                DontDestroyOnLoad(this.gameObject);
            }
        }

        class CustomView : MonoBehaviour
        {
            private IView _view;
            private IUnit _unit;
            private IAnimator _animtor;

            private Animator gAnimtor;

            public void SetView(IView view)
            {
                _view = view;
                view.TryGetCombineComponent<IUnit>(out _unit);
                if (view.TryGetCombineComponent<IAnimator>(out _animtor))
                {
                    gAnimtor = gameObject.AddComponent<Animator>();
                }


                //创建具体gameobject
                InitFacade();
            }

            private void InitFacade()
            {
                switch (_view.EntityType)
                {
                    case (int)EntityType.gear:
                        if (_view.SubType == (int) GearType.门机关1)
                        {
                            Debug.Log($"Stage/gear/{nameof(GearType.门机关1)}");
                            var obj = Resources.Load<GameObject>($"Stage/gear/{nameof(GearType.门机关1)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = new Vector3(3,0,3);
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }
                        if (_view.SubType == (int) GearType.地刺机关1)
                        {
                            Debug.Log($"Stage/gear/{nameof(GearType.地刺机关1)}");
                            var obj = Resources.Load<GameObject>($"Stage/gear/{nameof(GearType.地刺机关1)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = Vector3.zero;
                            transform.position = new Vector3(7.35f,0,0);
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }

                        if (_view.SubType == (int) GearType.地刺机关2)
                        {
                            Debug.Log($"Stage/gear/{nameof(GearType.地刺机关2)}");
                            var obj = Resources.Load<GameObject>($"Stage/gear/{nameof(GearType.地刺机关2)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = new Vector3(4.35f, 1, 3);
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }
                        if (_view.SubType == (int) GearType.地刺机关3)
                        {
                            Debug.Log($"Stage/gear/{nameof(GearType.地刺机关3)}");
                            var obj = Resources.Load<GameObject>($"Stage/gear/{nameof(GearType.地刺机关3)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = Vector3.zero;
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }
                        break;
                    case (int)EntityType.monster:
                        if (_view.SubType == (int) MonsterType.怪物1)
                        {
                            Debug.Log($"Stage/monster/{nameof(MonsterType.怪物1)}");
                            var obj = Resources.Load<GameObject>($"Stage/monster/{nameof(MonsterType.怪物1)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = new Vector3(11,0,0);
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }
                        break;
                    case (int)EntityType.hero:
                        if (_view.SubType == (int) HeroType.男)
                        {
                            Debug.Log($"Stage/monster/{nameof(HeroType.男)}");
                            var obj = Resources.Load<GameObject>($"Stage/hero/{nameof(HeroType.男)}");
                            var go = GameObject.Instantiate(obj);
                            go.transform.SetParent(transform);
                            go.transform.localPosition = Vector3.zero;
                            go.transform.localEulerAngles = Vector3.zero;
                            go.transform.localScale = obj.transform.localScale;
                        }
                        break;
                }
            }

            private void LateUpdate()
            {
                gameObject.SetActive(_view.IsInView);
                if (!_view.IsInView)
                    return;

                if (_unit != null)
                {
                    gameObject.transform.position = _unit.Position.ToVector();
                    gameObject.transform.localEulerAngles = _unit.Rotation.ToVector();
                }

                if (_animtor != null)
                {
                    //if(_animtor.animStateName != null && _animtor.animStateName.Equals(gAnimtor.cu))
                }
            }
        }
    }
    
}